home *** CD-ROM | disk | FTP | other *** search
- /* TBinder.m
- * Written By: Thomas Burkholder
- *
- * You may freely copy, distribute, and reuse the code in this example.
- * NeXT disclaims any warranty of any kind, expressed or implied, as to its
- * fitness for any particular use.
- */
-
- #import "TBinder.h"
-
- @implementation TBinder
-
- int returnsDouble(id oClass, SEL aSelector)
- {
- struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
-
- if ((p->method_types) && (p->method_types[0]=='d'))
- return 1;
- return 0;
- }
-
- int takesDouble(id oClass, SEL aSelector)
- {
- // modifiers always look like : "@16@8:12d16"
- struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
-
- if ((p->method_types) && (p->method_types[8]=='d'))
- return 1;
- return 0;
- }
-
- int returnsFloat(id oClass, SEL aSelector)
- {
- // modifiers always look like : "@16@8:12d16"
- struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
-
- if ((p->method_types) && (p->method_types[0]=='f'))
- return 1;
- return 0;
- }
-
- int takesFloat(id oClass, SEL aSelector)
- {
- struct objc_method *p = class_getInstanceMethod(oClass,aSelector);
-
- if ((p->method_types) && (p->method_types[8]=='f'))
- return 1;
- return 0;
- }
-
- - init
- {
- [super init];
- dataSource = nil;
- interface = nil;
- interfaceAccessor = (SEL)0;
- interfaceModifier = (SEL)0;
- dataSourceAccessor = (SEL)0;
- dataSourceModifier = (SEL)0;
- flags.verify = NO;
- flags.autoUpdate = YES;
- return self;
- }
-
- - setTarget:anObject { target = anObject; return self; }
- - target { return target; }
- - setAction:(SEL)anAction { action = anAction; return self; }
- - (SEL)action { return action; }
- - setDataSource:anObject { dataSource = anObject; return self; }
- - dataSource { return dataSource; }
- - setInterface:anObject { interface = anObject; return self; }
- - interface { return interface; }
- - setInterfaceAccessor:(SEL)aSel { interfaceAccessor = aSel; return self; }
- - (SEL)interfaceAccessor { return interfaceAccessor; }
- - setInterfaceModifier:(SEL)aSel { interfaceModifier = aSel; return self; }
- - (SEL)interfaceModifier { return interfaceModifier; }
- - setDataSourceAccessor:(SEL)aSel { dataSourceAccessor = aSel; return self; }
- - (SEL)dataSourceAccessor { return dataSourceAccessor; }
- - setDataSourceModifier:(SEL)aSel { dataSourceModifier = aSel; return self; }
- - (SEL)dataSourceModifier { return dataSourceModifier; }
- - setVerify:(BOOL)yn { flags.verify = yn; return self; }
- - (BOOL)verify { return flags.verify; }
- - setAutoUpdate:(BOOL)yn { flags.autoUpdate = yn; return self; }
- - (BOOL)autoUpdate { return flags.autoUpdate; }
-
- - updateInterface:sender
- {
- double (*doubleAcc)(id,SEL);
- float (*floatAcc)(id,SEL);
- id (*doubleMod)(id,SEL,double);
- id (*floatMod)(id,SEL,float);
- float f;
- double d;
-
- // objc_msgSend is stupid about returning float and double...
- if (returnsDouble([dataSource class], dataSourceAccessor)) {
- doubleAcc = (double (*)(id,SEL))[dataSource methodFor:dataSourceAccessor];
- d = doubleAcc(dataSource, dataSourceAccessor);
- if (takesDouble([interface class], interfaceModifier)) {
- doubleMod = (id (*)(id,SEL,double))[interface methodFor:interfaceModifier];
- doubleMod(interface,interfaceModifier,d);
- } else if (takesFloat([interface class], interfaceModifier)) {
- floatMod = (id (*)(id,SEL,float))[interface methodFor:interfaceModifier];
- floatMod(interface,interfaceModifier,(float)d);
- } else { // passing a float or a double to something that won't take it.
- fprintf(stderr,"TBinder: attempt to bind double to non-float/double\n");
- }
- } else if (returnsFloat([dataSource class], dataSourceAccessor)) {
- floatAcc = (float (*)(id,SEL))[dataSource methodFor:dataSourceAccessor];
- f = floatAcc(dataSource, dataSourceAccessor);
- if (takesFloat([interface class], interfaceModifier)) {
- floatMod = (id (*)(id,SEL,float))[interface methodFor:interfaceModifier];
- floatMod(interface,interfaceModifier,f);
- } else if (takesDouble([interface class],interfaceModifier)) {
- doubleMod = (id (*)(id,SEL,double))[interface methodFor:interfaceModifier];
- doubleMod(interface,interfaceModifier,(double)f);
- } else {
- fprintf(stderr,"TBinder: attempt to bind float to non-float/double\n");
- }
- } else { // Should cover ordinary stuff.
- objc_msgSend(interface,interfaceModifier,[dataSource perform:dataSourceAccessor]);
- }
- return self;
- }
-
- - updateDataSource:sender
- {
- double (*doubleAcc)(id,SEL);
- id (*doubleMod)(id,SEL,double);
- float (*floatAcc)(id,SEL);
- id (*floatMod)(id,SEL,float);
- float f;
- double d;
-
- if (target && action) {
- [target perform:action with:sender];
- }
- // objc_msgSend is stupid about returning float and double...
- if (returnsDouble([interface class], interfaceAccessor)) {
- doubleAcc = (double (*)(id,SEL))[interface methodFor:interfaceAccessor];
- d = doubleAcc(interface, interfaceAccessor);
- if (takesDouble([dataSource class],dataSourceModifier)) {
- doubleMod = (id (*)(id,SEL,double))[dataSource methodFor:dataSourceModifier];
- doubleMod(dataSource,dataSourceModifier,d);
- } else if (takesFloat([dataSource class],dataSourceModifier)) {
- floatMod = (id (*)(id,SEL,float))[dataSource methodFor:dataSourceModifier];
- floatMod(dataSource,dataSourceModifier,(float)d);
- } else {
- fprintf(stderr,"TBinder: attempt to bind double to non-float/double\n");
- }
- } else if (returnsFloat([interface class], interfaceAccessor)) {
- floatAcc = (float (*)(id,SEL))[interface methodFor:interfaceAccessor];
- f = floatAcc(interface, interfaceAccessor);
- if (takesFloat([dataSource class],dataSourceModifier)) {
- floatMod = (id (*)(id,SEL,float))[dataSource methodFor:dataSourceModifier];
- floatMod(dataSource,dataSourceModifier,f);
- } else if (takesDouble([dataSource class],dataSourceModifier)) {
- doubleMod = (id (*)(id,SEL,double))[dataSource methodFor:dataSourceModifier];
- doubleMod(dataSource,dataSourceModifier,(double)f);
- } else {
- fprintf(stderr,"TBinder: attempt to bind float to non-float/double\n");
- }
- } else { // Should cover ordinary stuff.
- objc_msgSend(dataSource,dataSourceModifier,[interface perform:interfaceAccessor]);
- }
- if (flags.verify) {
- [self updateInterface:sender];
- }
- return self;
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
- dataSource = NXReadObject(stream);
- interface = NXReadObject(stream);
- target = NXReadObject(stream);
- NXReadTypes(stream,":::::c",&action,&interfaceAccessor,
- &interfaceModifier,&dataSourceAccessor,
- &dataSourceModifier, &flags);
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- NXWriteObject(stream, dataSource);
- NXWriteObject(stream, interface);
- NXWriteObject(stream, target);
- NXWriteTypes(stream,":::::c",&action,&interfaceAccessor,
- &interfaceModifier,&dataSourceAccessor,
- &dataSourceModifier,&flags);
- return self;
- }
-
- @end
-